#include "stdio.h"
#include "dvc_common.h"

#define DVC_DEBUG_TEST 1

#define log_write printf

const char *dvc_cs_vs_pt_to_str(dvc_cs_vs_pt_t type)
{
    switch (type)
    {
    case dvc_cs_vs_pt_continuous:
        return "连续模式";
    case dvc_cs_vs_pt_1s:
        return "1s";
    case dvc_cs_vs_pt_2s:
        return "2s";
    case dvc_cs_vs_pt_4s:
        return "4s";
    case dvc_cs_vs_pt_8s:
        return "8s";
    case dvc_cs_vs_pt_16s:
        return "16s";
    case dvc_cs_vs_pt_32s:
        return "32s";
    case dvc_cs_vs_pt_64s:
        return "64s";
    default:
        return "Invalid type(无效数据)";
    }
}

const char *dvc_ld_en_to_str(dvc_ld_en_t type)
{
    switch (type)
    {
    case dvc_ld_en_auto:
    case dvc_ld_en_auto2:
        return "自动负载检测";
    case dvc_ld_en_disable:
        return "负载检测关闭";
    case dvc_ld_en_enable:
        return "负载检测开启";
    default:
        return "Invalid type(无效数据)";
    }
}

const char *dvc_vrm_to_str(dvc_vrm_t type)
{
    switch (type)
    {
    case dvc_vrm_auto:
    case dvc_vrm_auto2:
        return "自动模式";
    case dvc_vrm_disable:
        return "输出关闭";
    case dvc_vrm_enable:
        return "输出开启";
    default:
        return "Invalid type(无效数据)";
    }
}

const char *dvc_wdm_to_str(dvc_wdm_t type)
{
    switch (type)
    {
    case dvc_wdm_disable:
        return "超时保护关闭";
    case dvc_wdm_sleep:
        return "超时睡眠";
    case dvc_wdm_retry_sleep:
        return "超时重启VOUT, 无有效指令睡眠";
    case dvc_apm_reset_vout:
        return "超时重启VOUT, 不睡眠";
    default:
        return "Invalid type(无效数据)";
    }
}

const char *dvc_apm_to_str(dvc_apm_t type)
{
    switch (type)
    {
    case dvc_apm_enable:
        return "检测开启";
    case dvc_apm_vout:
        return "随 VOUT 输出开启而开启";
    case dvc_apm_cap:
        return "随 CAP 输出开启而开启";
    case dvc_apm_disable:
        return "检测关闭";
    default:
        return "Invalid type(无效数据)";
    }
}

__used static const uint32_t dvc_occt2uV[][16] = {
    {
        2300,
        5200,
        8100,
        10900,
        13800,
        16700,
        19600,
        22500,
        25300,
        28200,
        31100,
        34000,
        36900,
        42600,
        45500,
    },
    {
        4400,
        10100,
        15800,
        21500,
        27200,
        32900,
        38600,
        44300,
        50000,
        55700,
        61400,
        67100,
        72800,
        78600,
        84300,
        90000,
    },
};
static const char *const dvc_occt_to_str(uint8_t cp_gc, dvc_occt_t type)
{
    static const char *const cpgc02str[][16] = {
        {
            "2.3mV",
            "5.2mv",
            "8.1mv",
            "10.9mv",
            "13.8mv",
            "16.7mv",
            "19.6mv",
            "22.5mv",
            "25.3mv",
            "28.2mv",
            "31.1mv",
            "34.0mv",
            "36.9mv",
            "39.7mv",
            "42.6mv",
            "45.5mv",
        },
        {
            "4.4mv",
            "10.1mv",
            "15.8mv",
            "21.5mv",
            "27.2mv",
            "32.9mv",
            "38.6mv",
            "44.3mv",
            "50.0mv",
            "55.7mv",
            "61.4mv",
            "67.1mv",
            "72.8mv",
            "78.6mv",
            "84.3mv",
            "90.0mv",
        },
    };
    if (type > 15 || cp_gc > 1)
        return "Invalid type(无效数据)";
    return cpgc02str[cp_gc][type];
}
__used static const uint32_t dvc_scdt2uv[][16] =
    {
        {
            9700,
            15400,
            21100,
            26800,
            32600,
            38300,
            44000,
            49700,
            55400,
            61200,
            66900,
            72600,
            78300,
            84000,
            89800,
            95500,
        },
        {
            18800,
            30200,
            41500,
            52800,
            64200,
            75500,
            86800,
            98200,
            109500,
            120800,
            132100,
            143500,
            154800,
            166100,
            177500,
            188800,
        },
};
const char *dvc_scdt_to_str(uint8_t cp_gc, dvc_scdt_t type)
{
    static const char *const cpgc02str[][16] = {
        {
            "9.7mv",
            "15.4mv",
            "21.1mv",
            "26.8mv",
            "32.6mv",
            "38.3mv",
            "44.0mv",
            "49.7mv",
            "55.4mv",
            "61.2mv",
            "66.9mv",
            "72.6mv",
            "78.3mv",
            "84.0mv",
            "89.8mv",
            "95.5mv",
        },
        {
            "18.8mv",
            "30.2mv",
            "41.5mv",
            "52.8mv",
            "64.2mv",
            "75.5mv",
            "86.8mv",
            "98.2mv",
            "109.5mv",
            "120.8mv",
            "132.1mv",
            "143.5mv",
            "154.8mv",
            "166.1mv",
            "177.5mv",
            "188.8mv",
        },
    };
    if (type > 15 || cp_gc > 1)
        return "Invalid type(无效数据)";
    return cpgc02str[cp_gc][type];
}

const char *dvc_occd_to_str(dvc_occd_t type)
{
    switch (type)
    {
    case dvc_occd_32ms:
        return "32ms";
    case dvc_occd_80ms:
        return "80ms";
    case dvc_occd_160ms:
        return "160ms";
    case dvc_occd_320ms:
        return "320ms";
    case dvc_occd_640ms:
        return "640ms";
    case dvc_occd_1280ms:
        return "1280ms";
    case dvc_occd_2560ms:
        return "2560ms";
    case dvc_occd_5120ms:
        return "5120ms";
    default:
        return "Invalid type(无效数据)";
    }
}

const char *dvc_scdd_to_str(dvc_occd_t type)
{
    switch (type)
    {
    case dvc_scdd_400us:
        return "400us";
    case dvc_scdd_500us:
        return "500us";
    case dvc_scdd_900us:
        return "900us";
    case dvc_scdd_1600us:
        return "1600us";
    default:
        return "Invalid type(无效数据)";
    }
}

void dvc_cfg_print(void *param, uint32_t uR)
{
    if (!param)
    {
        log_write("Invalid parameter(无效参数)\n");
        return;
    }
    dvc_reg_cfg_t *cfg = param;
    log_write("组 0 ---------------------------------------------------\n");
    log_write("CFG0 Byte0 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[0]);
    log_write("CHG (充电管驱动)     : %s\n", cfg->cfg0.chg_en ? "由硬件保护模块决定" : "关闭");
    log_write("DSG (放电管驱动)     : %s\n", cfg->cfg0.dsg_en ? "由硬件保护模块决定" : "关闭");
    log_write("Vref (参考电压)      : %s\n", cfg->cfg0.vref_vs ? "3.3 V" : "2.5 V");
    log_write("Vout (LDO 输出电压)  : %s\n", cfg->cfg0.vout_vs ? "3.3 V" : "2.5 V");
    log_write("VoutEn(LDO 输出使能) : %s\n", cfg->cfg0.vout_en ? "开启" : "关闭");
    log_write("CP_EN (电流硬件保护) : %s\n", cfg->cfg0.cp_en ? "开启" : "关闭");
    log_write("CS_EN (电流传感通道) : %s\n", cfg->cfg0.cs_en ? "开启" : "关闭");
    log_write("VS_EN (电压传感通道) : %s\n", cfg->cfg0.vs_en ? "开启" : "关闭");

    log_write("\nCFG0 Byte1 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[1]);
    log_write("PED_EN(被动均衡驱动器): \n");
    log_write("\tBAT1 : %d\n", cfg->cfg0.cb1);
    log_write("\tBAT2 : %d\n", cfg->cfg0.cb2);
    log_write("\tBAT3 : %d\n", cfg->cfg0.cb3);
    log_write("\tBAT4 : %d\n", cfg->cfg0.cb4);
    log_write("\tBAT5 : %d\n", cfg->cfg0.cb5);
    log_write("\tBAT6 : %d\n", cfg->cfg0.cb6);

    log_write("\nCFG0 Byte2 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[2]);
    log_write("电流传感通道轮询周期 : %s\n", dvc_cs_vs_pt_to_str(cfg->cfg0.cs_pt));
    log_write("电压传感通道轮询周期 : %s\n", dvc_cs_vs_pt_to_str(cfg->cfg0.vs_pt));
    log_write("LD_EN (负载检测使能) : %s\n", dvc_ld_en_to_str(cfg->cfg0.ld_en));

    log_write("\nCFG0 Byte3 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[3]);
    log_write("VRM (Vref 工作模式)         : %s\n", dvc_vrm_to_str(cfg->cfg0.vrm));
    log_write("WDM Vout看门狗超时保护模式  : %s\n", dvc_wdm_to_str(cfg->cfg0.wdm));
    log_write("APM(警报下拉检测模式)       : %s\n", dvc_apm_to_str(cfg->cfg0.apm));

    log_write("\nCFG0 Byte4 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[4]);
    log_write("DSG Alarm(放电管驱动输出警报选择) 0 有效: \n");
    log_write("\t 放电过流 : %d\n", cfg->cfg0.dsg_ocd);
    log_write("\t 放电短路 : %d\n", cfg->cfg0.dsg_scd);
    log_write("\t 电池欠压 : %d\n", cfg->cfg0.dsg_uv);
    log_write("\t 电池过压 : %d\n", cfg->cfg0.dsg_ov);
    log_write("\t DSG 控制 : %d\n", cfg->cfg0.dsg_alt);
    log_write("\t 电流故障 : %d\n", cfg->cfg0.dsg_cs);
    log_write("\t 电压故障 : %d\n", cfg->cfg0.dsg_vs);
    log_write("\t 充电过流 : %d\n", cfg->cfg0.dsg_occ);

    log_write("\nCFG0 Byte5 : 0x%02X\n", ((uint8_t *)&cfg->cfg0)[5]);
    log_write("CHG Alarm(充电管驱动输出警报选择) 0 有效: \n");
    log_write("\t 充电过流 : %d\n", cfg->cfg0.chg_ocd);
    log_write("\t 充电短路 : %d\n", cfg->cfg0.chg_scd);
    log_write("\t 电池欠压 : %d\n", cfg->cfg0.chg_uv);
    log_write("\t 电池过压 : %d\n", cfg->cfg0.chg_ov);
    log_write("\t CHG 控制 : %d\n", cfg->cfg0.chg_alt);
    log_write("\t 电流故障 : %d\n", cfg->cfg0.chg_cs);
    log_write("\t 电压故障 : %d\n", cfg->cfg0.chg_vs);
    log_write("\t 充电过流 : %d\n", cfg->cfg0.chg_occ);

    log_write("\n组 1 ---------------------------------------------------\n");
    log_write("CFG1 Byte0 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[0]);
    log_write("CP GC (电流硬件保护检测倍率): %s\n", cfg->cfg1.cp_gc ? "X2" : "X1");
    uint32_t v = dvc_occt2uV[cfg->cfg1.cp_gc][cfg->cfg1.occt] * 1000 / uR;
    log_write("OCCT (充电过流保护阈值)     : %s(%ld.%03ld A)\n", dvc_occt_to_str(cfg->cfg1.cp_gc, cfg->cfg1.occt), v / 1000, v % 1000);
    log_write("OCCD (充电过流保护延时)     : %s\n", dvc_occd_to_str(cfg->cfg1.occd));

    log_write("\nCFG1 Byte1 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[1]);
    v = dvc_occt2uV[cfg->cfg1.cp_gc][cfg->cfg1.ocdt] * 1000 / uR;
    log_write("OCDT (放电过流保护阈值) : %s(%ld.%03ld A)\n", dvc_occt_to_str(cfg->cfg1.cp_gc, cfg->cfg1.ocdt), v / 1000, v % 1000);
    log_write("OCCD (放电过流保护延时) : %s\n", dvc_occd_to_str(cfg->cfg1.ocdd));

    log_write("\nCFG1 Byte2 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[2]);
    v = dvc_scdt2uv[cfg->cfg1.cp_gc][cfg->cfg1.scdt] * 1000 / uR;
    log_write("SCDT (放电短路保护阈值) : %s(%ld.%03ld A)\n", dvc_scdt_to_str(cfg->cfg1.cp_gc, cfg->cfg1.scdt), v / 1000, v % 1000);
    log_write("SCDD (放电短路保护延时) : %s\n", dvc_scdd_to_str(cfg->cfg1.scdd));

    log_write("\nCFG1 Byte3 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[3]);
    log_write("UVD  (电池欠压保护延时) : %dS\n", 1 << (cfg->cfg1.uvd + cfg->cfg1.uvd ? 1 : 0));
    log_write("OVD  (电池过压保护延时) : %dS\n", 1 << cfg->cfg1.ovd);
    log_write("CADCTM(电流采样时间选择): %s\n", cfg->cfg1.cadc_tm ? "256ms" : "64ms");

    log_write("\nCFG1 Byte4 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[4]);
    log_write("OVT  (电池过压保护阈值) : %d.%dV\n", (cfg->cfg1.ovt + 546) * 586 / 100000, ((cfg->cfg1.ovt + 546) * 586 / 100) % 1000);

    log_write("\nCFG1 Byte5 : 0x%02X\n", ((uint8_t *)&cfg->cfg1)[5]);
    log_write("UVT  (电池欠压保护阈值) : %d.%dV\n", (cfg->cfg1.uvt + 324) * 586 / 100000, ((cfg->cfg1.uvt + 324) * 586 / 100) % 1000);
}

#if DVC_DEBUG_TEST
#include "string.h"
int main(int args, char **argv)
{
    static const uint8_t data[2][6] = {
        {0xfc, 0x0f, 0x00, 0xe0, 0x88, 0x07},
        {0x02, 0x02, 0x01, 0x20, 0x4d, 0x9a},
    };
    dvc_reg_cfg_t cfg = {0};
    memcpy(&cfg, data, sizeof(data));
    dvc_cfg_print(&cfg, 1000);
    return 0;
}
#endif
